package com.itwang.xiaohashu.auth.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.itwang.framework.common.enums.DeletedEnum;
import com.itwang.framework.common.enums.StatusEnum;
import com.itwang.framework.common.exception.BizException;
import com.itwang.framework.common.reponse.Response;
import com.itwang.framework.common.util.JsonUtils;
import com.itwang.xiaohashu.auth.constant.RedisKeyConstants;
import com.itwang.xiaohashu.auth.constant.RoleConstants;
import com.itwang.xiaohashu.auth.domain.dataobject.UserDO;
import com.itwang.xiaohashu.auth.domain.dataobject.UserRoleDO;
import com.itwang.xiaohashu.auth.domain.mapper.UserDOMapper;
import com.itwang.xiaohashu.auth.domain.mapper.UserRoleDOMapper;
import com.itwang.xiaohashu.auth.enums.LoginTypeEnum;
import com.itwang.xiaohashu.auth.enums.ResponseCodeEnum;
import com.itwang.xiaohashu.auth.model.vo.user.UserLoginReqVO;
import com.itwang.xiaohashu.auth.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;


@Service
@Slf4j
public class UserServiceImpl implements UserService {


    @Resource
    private UserDOMapper userDOMapper;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    @Resource
    private UserRoleDOMapper userRoleDOMapper;

    @Resource
    private TransactionTemplate transactionTemplate;

    /**
     * 登录与注册
     * @param userLoginReqVO
     * @return
     */
    @Override
    public Response<String> loginAndRegister(UserLoginReqVO userLoginReqVO) {
        String phone = userLoginReqVO.getPhone();
        Integer type = userLoginReqVO.getType();

        LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(type);

        Long userId=null;
        switch(loginTypeEnum){
            case VERIFICATION_CODE : // 验证码登录
                String verificationCode = userLoginReqVO.getCode();

                // 校验入参验证码是否为空
                // if(StringUtils.isBlank(verificationCode)){
                //     return Response.fail(ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode(),"验证码不能为空");
                // }
                Preconditions.checkArgument(StringUtils.isNotBlank(verificationCode), "验证码不能为空");

                // 构建验证码 Redis key
                String key = RedisKeyConstants.buildVerificationCodeKey(phone);
                // 查询存储在 Redis 中的验证码
                String sentCode = (String)redisTemplate.opsForValue().get(key);
                if(!StringUtils.equals(verificationCode,sentCode)){
                    throw new BizException(ResponseCodeEnum.VERIFICATION_CODE_ERROR);
                }

                UserDO userDO = userDOMapper.selectByPhone(phone);

                log.info("==> 用户是否注册, phone: {}, userDO: {}", phone, JsonUtils.toJsonString(userDO));
                // 判断是否注册
                if (Objects.isNull(userDO)) {
                    // 若此用户还没有注册，系统自动注册该用户
                    userId=registerUser(phone);

                } else {
                    // 已注册，则获取其用户 ID
                    userId = userDO.getId();
                }

                break;
            case PASSWORD :  // 密码登录

                // todo
                break;
            default:
                break;
        }

        // SaToken 登录用户，并返回 token 令牌
        StpUtil.login(userId);
        // 获取 Token 令牌
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();

        // 返回 Token 令牌
        return Response.success(tokenInfo.tokenValue);
    }


    /**
     * 系统自动注册用户
     * @param phone
     * @return
     */

    public Long registerUser(String phone){


        // 编程式事务
        return transactionTemplate.execute(status -> {
           try{
               Long xiaohashuId = redisTemplate.opsForValue().increment(RedisKeyConstants.XIAOHASHU_ID_GENERATOR_KEY);

               UserDO userDO = UserDO.builder()
                       .phone(phone)
                       .xiaohashuId(String.valueOf(xiaohashuId))
                       .nickname("小红薯" + xiaohashuId)
                       .status(StatusEnum.ENABLE.getValue())
                       .createTime(LocalDateTime.now())
                       .updateTime(LocalDateTime.now())
                       .isDeleted(DeletedEnum.NO.getValue()) // 逻辑删除
                       .build();


               userDOMapper.insert(userDO);



               // 获取刚刚添加入库的用户 ID
               Long userId = userDO.getId();

               // 给该用户分配一个默认角色
               UserRoleDO userRoleDO = UserRoleDO.builder()
                       .userId(userId)
                       .roleId(RoleConstants.COMMON_USER_ROLE_ID)
                       .createTime(LocalDateTime.now())
                       .updateTime(LocalDateTime.now())
                       .isDeleted(DeletedEnum.NO.getValue())
                       .build();

               userRoleDOMapper.insert(userRoleDO);
               // 将该用户的角色 ID 存入 Redis 中
               List<Long> roles = Lists.newArrayList();
               roles.add(RoleConstants.COMMON_USER_ROLE_ID);
               String userRolesKey = RedisKeyConstants.buildUserRoleKey(phone);
               redisTemplate.opsForValue().set(userRolesKey, JsonUtils.toJsonString(roles));

               return userId;
           }catch(Exception e){
               status.setRollbackOnly(); //标记事务回滚
               log.error("==> 系统注册用户异常: ", e);
               return null;
           }
        });


    }
}
